package cn.pconline.autoclub.web.admin;

import java.io.IOException;
import java.io.OutputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.http.impl.cookie.DateUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.gelivable.auth.entity.GeliSession;
import org.gelivable.dao.GeliDao;
import org.gelivable.log.GeliLogFacade;
import org.gelivable.web.Env;
import org.gelivable.web.EnvUtils;
import org.gelivable.webmvc.JSONBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.pconline.autoclub.entity.CheckIn;
import cn.pconline.autoclub.entity.ClubMember;
import cn.pconline.autoclub.entity.MemberApplication;
import cn.pconline.autoclub.entity.User;
import cn.pconline.autoclub.service.BaseService;
import cn.pconline.autoclub.service.CheckInService;
import cn.pconline.autoclub.service.MemberService;
import cn.pconline.autoclub.service.UserService;
import cn.pconline.autoclub.util.Pager;

/**
 * @author 作者 guoqiang
 * @version 2014-5-23 用户管理
 */
@Controller
@RequestMapping("/admin")
public class AdminUserController {

    @Autowired
    private UserService userService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private CheckInService checkInService;
    @Autowired
    private GeliDao geliDao;
    @Autowired
    private BaseService baseService;
    
    private static final Logger log = LoggerFactory.getLogger(AdminUserController.class);

    /**
     * 用户列表
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/account/list")
    public String list(HttpServletRequest request, HttpServletResponse response) {
        Env env = EnvUtils.getEnv();
        long uid = env.paramLong("userId", 0);
        String userName = env.param("userName", "");
        int pageNo = env.paramInt("pageNum", 1);
        int pageSize = env.paramInt("pageSize", 20);
        String orderField = env.param("orderField", "create_at");
        String orderDirection = env.param("orderDirection", "desc");

        Pager<User> pager = userService.getUserByIdOrName(uid, userName, pageNo, pageSize, orderField, orderDirection);

        request.setAttribute("pager", pager);
        request.setAttribute("uid", uid);
        request.setAttribute("userName", userName);
        request.setAttribute("orderField", orderField);
        request.setAttribute("orderDirection", orderDirection);
        return "/admin/club/userList";
    }

    /**
     * 导出用户列表
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/account/listBatchExport.do", produces = {"application/octet-stream"})
    public void listBatchExport(HttpServletRequest request, HttpServletResponse response) {
        Env env = EnvUtils.getEnv();
        long uid = env.paramLong("userId", 0);
        String userName = env.param("userName", "");
        int pageNo = env.paramInt("pageNum", 1);
        int pageSize = env.paramInt("pageSize", 1000);
        String orderField = env.param("orderField", "create_at");
        String orderDirection = env.param("orderDirection", "desc");

        Pager<User> pager = userService.getUserByIdOrName(uid, userName, pageNo, pageSize, orderField, orderDirection);
        /**
         * 生成excel文件
         */
        String[] cellString = new String[]{"用户ID", "用户名", "创建时间", "用户昵称", "真实姓名", "性别", "地址", "电话", "是否认证", "生日"};
        HSSFWorkbook work = new HSSFWorkbook();
        HSSFSheet sheet = work.createSheet("用户列表");
        HSSFRow row = sheet.createRow(0);
        for (int i = 0; i < cellString.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(cellString[i]);
        }
        /**
         * 根据分页数据生成excel文件
         */
        if (pager.getResultList() != null) {
            for (int curPage = pageNo; curPage <= pager.getPageCount(); curPage++) {
                // 数据一页一页加载
                if (curPage != pageNo) {
                    pager = userService.getUserByIdOrName(uid, userName, curPage, pageSize, orderField, orderDirection);
                }
                //petrol
                for (int i = 0; i < pager.getResultList().size(); i++) {
                    User u = pager.getResultList().get(i);
                    HSSFRow rowData = sheet.createRow(((curPage - 1) * pageSize) + i + 1);
                    rowData.createCell(0).setCellValue(u.getUid());
                    rowData.createCell(1).setCellValue(u.getUsername());
                    rowData.createCell(2).setCellValue(DateUtils.formatDate(u.getCreateAt()));
                    rowData.createCell(3).setCellValue(u.getNickname());
                    rowData.createCell(4).setCellValue(u.getTruename());
                    rowData.createCell(5).setCellValue(u.getGender() == 0 ? "男" : "女");
                    String province = u.getProvince();
                    String city = u.getCity();
                    rowData.createCell(6).setCellValue((province == null ? "" : province) + (city == null ? "" : city));
                    rowData.createCell(7).setCellValue(u.getPhone());
                    rowData.createCell(8).setCellValue(u.getVip() == 0 ? "否" : "是");
                    rowData.createCell(9).setCellValue(u.getBirthday() == null ? "" : DateUtils.formatDate(u.getBirthday()));
                }
            }
        }
        try {
            //设置返回数据类型
            response.setContentType("application/vnd.ms-excel;charset=GBK");
            //设置返回的文件名
            response.setHeader("Content-Disposition",
                    "attachment;Filename=user.xls");
            OutputStream out = response.getOutputStream();
            work.write(out);
            out.flush();
            out.close();
        } catch (IOException ex) {
        	log.error("listBatchExport fail!", ex);
        }
    }

    /**
     * 用户详情
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/account/detail")
    public String detail(HttpServletRequest request, HttpServletResponse response) {
        Env env = EnvUtils.getEnv();
        long uid = env.paramLong("userId", 0);
        User user = userService.findUser(uid);
        List<MemberApplication> listApplication = memberService.findMemberApplication(uid, 0, false);
        List<ClubMember> listMember = memberService.listClubMemberByUser(uid);

        request.setAttribute("user", user);
        request.setAttribute("listApplication", listApplication);
        request.setAttribute("listMember", listMember);
        return "/admin/club/userDetail";
    }

    /**
     * 车友会删除会员
     *
     * @param req
     * @param resp type=1 申请中的信息 type = 2 会员信息
     * @return
     */
    @RequestMapping(value = "/user/memberDelete.do")
    public String memberDelete(HttpServletRequest req, HttpServletResponse resp) {
        Env env = EnvUtils.getEnv();
        GeliLogFacade.log();
        long memberId = env.paramLong("id", 0);
        int type = env.paramInt("type", 0);
        long adminId = GeliSession.getCurrentUser().getUserId();
        long i = memberService.removeMemberByEdit(type, adminId, memberId);
        if (i > 0) {
            successMsg("删除成功", "account-detail", resp);
        } else {
            errorMsg("删除失败", resp);
        }
        return null;
    }

    private void errorMsg(String msg, HttpServletResponse resp) {
        try {
            resp.setCharacterEncoding("UTF-8");
            resp.getWriter().println(
                    new JSONBuilder()
                    .put("statusCode", 300)
                    .put("message", msg)
                    .toString());
        } catch (IOException ex) {
            log.error("set errorMsg fail!", ex);
        }
    }

    private void successMsg(String msg, String navTabId, HttpServletResponse resp) {
        try {
            String rs = StringUtils.isEmpty(msg) ? "操作成功" : msg;
            resp.setCharacterEncoding("UTF-8");
            resp.getWriter().println(new JSONBuilder()
                    .put("statusCode", 200)
                    .put("message", rs)
                    .put("navTabId", navTabId)
                    .toString());
        } catch (IOException ex) {
            log.error("set successMsg fail!", ex);
        }
    }
    
    @RequestMapping(value = "/dev/repairCheckin.do", method = RequestMethod.POST)
    @ResponseBody
    public String repairCheckin(HttpServletRequest req, HttpServletResponse resp) {
        String userIds = req.getParameter("userIds");
        String clubIds = req.getParameter("clubIds");
        if(userIds == null || clubIds == null) {
            return "not found userIds|clubIds parameter";
        }
        String[] userIdArr = userIds.split(",");
        String[] clubIdArr = clubIds.split(",");
        if(userIdArr.length != clubIdArr.length) {
            return "userIds & clubIds count not equals";
        }
        String sql = "select a.* from ("
                + "select * from ac_member_checkin_record_201501 "
                + "union all select * from ac_member_checkin_record_201412 "
                + "union all select * from ac_member_checkin_record_201411 "
                + "union all select * from ac_member_checkin_record_201410 "
                + "union all select * from ac_member_checkin_record_201409 "
                + "union all select * from ac_member_checkin_record_201408 "
                + "union all select * from ac_member_checkin_record_201407 "
                + "union all select * from ac_member_checkin_record_201406 "
                + "union all  select * from ac_member_checkin_record_201405 "
                + "union all select * from ac_member_checkin_record_201404 " //group by DATE_FORMAT(create_at,'%Y%m%d')
                + ")a where a.user_id = ? and a.club_id = ? order by create_at desc";
        System.out.println("checkin record sql: " + sql);
        Map<String, Integer> reVal = new HashMap<String, Integer>();
        for(int i = 0, l = userIdArr.length; i < l; i++) {
            final String fuid = userIdArr[i];
            final String fcid = clubIdArr[i];
            int checkIns = geliDao.getJdbcTemplate().query(sql, new Object[]{fuid, fcid}, new ResultSetExtractor<Integer>() {
                @Override
                public Integer extractData(ResultSet rs) throws SQLException, DataAccessException {
                    int count = 1;
                    int checkinYmd = 0;
                    Date toDayCreateAt = null;
                    Date now  = new Date();
                    Date yesterday = org.apache.commons.lang.time.DateUtils.addDays(now, -1);
                    if(rs.next()) {
                        Date createAt = rs.getDate("create_at");
                        if(createAt == null || createAt.before(org.apache.commons.lang.time.DateUtils.truncate(yesterday, Calendar.DAY_OF_MONTH))) {
                            System.out.println("today and yesterday neither not checkIn " + createAt + " before " + yesterday);
                            return 0;
                        }
                        count++;
                    }
                    while (rs.next()) {
                        Date createAt = rs.getDate("create_at");
                        int ymd = cn.pconline.autoclub.util.DateUtils.formatData2YMD(createAt);
                        System.out.println("checkin record "+fuid+"-"+fcid+" create_at: "+createAt+", "+checkinYmd);
                        if(toDayCreateAt != null) {
                            Date addDate = org.apache.commons.lang.time.DateUtils.addDays(createAt, 1);
                            if(checkinYmd - ymd != 0 && org.apache.commons.lang.time.DateUtils.truncatedEquals(toDayCreateAt, addDate, Calendar.DAY_OF_MONTH)) {
                                count++;
                                toDayCreateAt = createAt;
                                checkinYmd = ymd;
                            }
                        } else {
                            toDayCreateAt = createAt;
                            checkinYmd = ymd;
                        }
                    }
                    return count;
                }
            });
            //Map<String, Object> params = new HashMap<String, Object>();
            //params.put("user_id", fuid);
            //params.put("club_id", fcid);
            //CheckIn checkIn = baseService.findUniqueLongKeyObject(CheckIn.class, Long.valueOf(fcid), params);
            //baseService.findUniqueLongKeyObject(type, sql, params)
            //CheckIn checkIn = checkInService.getCheckInStatus(Long.valueOf(fuid), Long.valueOf(fcid));
            String checkInSql = "select * from "+geliDao.getTableName(CheckIn.class, Long.valueOf(fcid))+" where user_id = ? and club_id = ? order by total_checkins desc";
            System.out.println("checkin sql: " + sql);
            List<CheckIn> checkinList = geliDao.list(CheckIn.class, Long.valueOf(fcid), checkInSql, fuid, fcid);
            if(checkinList != null) {
                CheckIn repairCheckin = null;
                for(int j = 0, s = checkinList.size(); j < s; j++) {
                    if(j == 0) {
                        repairCheckin = checkinList.get(j);
                    } else {
                        CheckIn checkIn = checkinList.get(j);
                        repairCheckin.setTotalCheckIns(repairCheckin.getTotalCheckIns()+checkIn.getTotalCheckIns());
                        Date repairLastChcekinAt = repairCheckin.getLastCheckInAt();
                        Date lastChcekinAt = checkIn.getLastCheckInAt();
                        if(lastChcekinAt != null) {
                            if(repairLastChcekinAt == null || lastChcekinAt.after(repairLastChcekinAt)) {
                                repairCheckin.setLastCheckInAt(lastChcekinAt);
                                repairCheckin.setLastCheckinYmd(cn.pconline.autoclub.util.DateUtils.formatData2YMD(lastChcekinAt));
                            }
                        }
                        geliDao.delete(checkIn, checkIn.getId());
                    }
                }
                reVal.put(fuid+"-"+fcid, checkIns);
                repairCheckin.setContinuousCheckIns(checkIns);
                geliDao.update(repairCheckin);
            }
        }
        System.out.println("checkin record result: " + reVal);
        return reVal.toString();
    }
}
